package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
/*为啥udp的不管关闭socket文件，因为全程都在用，socket只有一个，
但是tcp不一样，每次来一个请求，就分配给客户端一个socket用来传输响应的数据，按理说哦一个文件不用了就得关闭，
while那里要处理很多的请求，所以旧的socket文件不用的scoket文件要及时进行关闭，因为一个进程打开的文件是有上限的*/
public class TcpEchoServer {
    //clientSocket就是内场服务的小姐姐，每个客户都会有小姐姐进行服务
    //serverSocket只有一个，clientSocket会给每个客户分配一个
    //serverSocket相当于是拉客的人（只有一个）
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动！");
        while (true) {
            //accept方法就是客户端来一个请求服务器就是接受连接，然后给一个socket文件去进行传输响应的数据
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }
    //通过这个方法来处理一个连接
    //读取请求
    //根据读取的请求计算响应
    //把响应的结果发送回给客户端
    //tcp是面向字节流的，所以在读数据的时候也是通过socket来读取数据

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线！\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //try（）这种写法，（ ）种允许写多个流，每个流之间是用 ; 来进行分割的
        try (InputStream inputStream = clientSocket.getInputStream();//这行代码的意思就是以字节流的方式来读取数据
             OutputStream outputStream = clientSocket.getOutputStream()) {//它的意思就是以字节流的方式来写数据
            /*但是它读是读的请求，从哪到哪里算是一个请求呢，此时就做一个约定：每读到一个\n就是一个请求
             * */
            Scanner scanner = new Scanner(inputStream);//scanner是以字符流来处理数据的
            PrintWriter printWriter =new PrintWriter(outputStream);//它的意思就是把outputStream（字节流）变成一个字符串
            while (true) {
                //1.读取请求
                if (!scanner.hasNext()) {//注意读写数据的本体是getInputStream和getOutputStream，scanner和PrintWrite只是套壳
                    //将字节流转换为字符串进行处理
                    //读取的流到了结尾了（也就是对端的连接关闭了）
                    System.out.printf("[%s:%d] 客户端下线！\n",clientSocket.getInetAddress(),toString(),
                            clientSocket.getPort());
                    break;
                }
                //没读到结尾，直接使用scanner来读取一段字符串(就一直读取字符串)
                String request = scanner.next();
                //2.根据请求计算响应
                String response = process(request);
                //3.把响应写回到客户端   要记住：响应里也是要带上换行的
                //由于计算完成之后的数据是一个字符串，所以在发送回给客户端时也变成字符串就得了
                printWriter.println(request);
                printWriter.flush();
                System.out.printf("[%s:%d] req: %s, resp: %s\n",clientSocket.getInetAddress(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(909);
        tcpEchoServer.start();
    }
}
